import { isNumber } from 'wot-design-uni/components/common/util'

// db文件存放址
const DB_PARH = '_doc/pdaapp.db'

/** 数据库是否打开--打开了就返回true,否则返回false
 * @param {Object} name 数据库名称
 * @param {Object} path 数据库地址，uniapp推荐以下划线为开头
 */
export function isOpen(name) {
  return plus.sqlite.isOpenDatabase({ name, path: DB_PARH })
}

/** 创建数据库或者打开
 * @param {Object} name  数据库名称
 * @param {Object} path  数据库地址，uniapp推荐以下划线为开头
 */
export function openSqlite(name) {
  return new Promise((resolve, reject) => {
    if (isOpen(name)) {
      resolve(true)
      return
    }
    // 这plus.sqlite只在手机上运行
    plus.sqlite.openDatabase({
      name, // 数据库名称
      path: DB_PARH, // 数据库地址，uniapp推荐以下划线为开头
      success(e) {
        resolve(e) // 成功回调
        console.log('e', e)
        console.log('openDatabase success', name)
      },
      fail(e) {
        console.log('openSqlite err', e)
        reject(e) // 失败回调
      },
    })
  })
}

// 在该数据库里创建表格/添加数据
// 数据库不能存对象，数组  需要转json后再存
/** 执行sql命令 对数据库  执行增删改等操作的SQL语句
 * @param {Object} name 数据库名称
 * @param {Object} sql sql命令
 */
export function executeSql(name, sql) {
  console.log('sql', sql)
  return new Promise((resolve, reject) => {
    plus.sqlite.executeSql({
      name,
      sql,
      success(e) {
        resolve(e)
      },
      fail(e) {
        console.log('executeSql err', e)
        reject(e)
      },
    })
  })
}

/** 执行查询的SQL语句
 * @param {Object} name 数据库名称
 * @param {Object} sql sql命令
 */
export function selectSql(name, sql) {
  console.log('sql', sql)
  return new Promise((resolve, reject) => {
    if (!name || !sql) reject(new Error('参数异常'))
    plus.sqlite.selectSql({
      name,
      sql,
      success(e) {
        resolve(e)
      },
      fail(e) {
        console.log('selectSql err', e)
        reject(e)
      },
    })
  })
}

/** 关闭数据库
 * @param {Object} name 数据库名称
 */
export function closeSQL(name) {
  return new Promise((resolve, reject) => {
    plus.sqlite.closeDatabase({
      name,
      success(e) {
        resolve(e)
      },
      fail(e) {
        console.log('closeSQL err', e)
        reject(e)
      },
    })
  })
}

/**
 * 执行事务
 * @param {Object} name 数据库名称
 * @param {Object} operation begin（开始事务）、commit（提交）、rollback（回滚）
 */
export function transactionDB(name, operation) {
  return new Promise((resolve, reject) => {
    plus.sqlite.transaction({
      name,
      operation,
      success: function (e) {
        resolve(operation)
      },
      fail: function (e) {
        console.log('transaction failed: ' + JSON.stringify(e))
        reject(operation)
      },
    })
  })
}

/** 获取建表sql */
export const getCreateSql = (arrs: SqlCreateItem[]) => {
  const newarrs = arrs.map((item) => {
    return [
      `${item.name} ${item.type}`,
      item.primary ? 'PRIMARY KEY' : '',
      item.notNull ? 'NOT NULL' : '',
      item.default
        ? `DEFAULT ${isNumber(item.default) ? item.default : item.default.toString()}`
        : '',
    ].join(' ')
  })
  return `(${newarrs.join(',')})`
}

/** 获取 inset sql */
export const getInsetSql = <T>(tableConfig: SqlCreateItem[], arrs: T[]) => {
  const newArrs = arrs.map((item) => {
    return `(${tableConfig
      .map((config) => {
        const value = item[config.name]
        /** 创建时间 */
        if (config.name === 'create_at') {
          return `'${Date.now().toString()}'`
        }
        if (config.type.includes('VARCHAR')) return `'${value}'`
        if (!value) throw new Error('数据异常')
        return value
      })
      .join(',')})`
  })
  return `${newArrs.join(',')}`
}

/** 获取 Where and set sql */
export const getWhereAndSetSql = <T>(tableConfig: SqlCreateItem[], query: T) => {
  const newQuery = tableConfig.map((config) => {
    const value = query[config.name]
    if ([undefined, null, undefined].includes(value)) return ''
    if (config.type.includes('VARCHAR')) return `${config.name}='${value}'`
    return `${config.name}=${value}`
  })
  return newQuery.filter((v) => v).join(' AND ')
}

/** 获取 Where sql */
export const getWhereSql = <T>(tableConfig: SqlCreateItem[], query: T) => {
  if (Object.keys(query).length === 0) return ''
  return `WHERE ${getWhereAndSetSql(tableConfig, query)}`
}

/** 获取 SET sql */
export const getSetSql = <T>(tableConfig: SqlCreateItem[], query: T) => {
  if (Object.keys(query).length === 0) return ''
  return `SET ${getWhereAndSetSql(tableConfig, query)}`
}

/** 获取 Where sql */
export const getLimitSql = (query?: QueryPage) => {
  const { pageSize = 20, pageNum = 1 } = query || {}
  return `limit ${pageSize * (pageNum - 1)},${pageSize}`
}

/** 批量删除sql */
export const getDelsSql = <T>(tableConfig: SqlCreateItem[], arrs: T[]) => {
  const primaryItem = tableConfig.find((item) => item.primary)
  const newArrs = arrs
    .map((item) => {
      const value = item[primaryItem.name]
      if (primaryItem.type.includes('VARCHAR')) return `'${value}'`
      return value
    })
    .filter((item) => item)
    .join(',')
  return `where ${primaryItem.name} in (${newArrs})`
}

/** 建表类型 */
export interface SqlCreateItem {
  /** 字段名 */
  name: string
  /** 数据类型 */
  type: string
  /** 是否是主键 */
  primary?: boolean
  /** 是否不能为空 */
  notNull?: boolean
  /** 备注 */
  comment?: string
  /** 默认值 */
  default?: string | number
}

export interface QueryPage {
  pageSize: number
  pageNum: number
}

/**
 * 创建sqllite方法
 * - ** TS 泛型 必传
 * @param {string} TABLE_NAME 表名称
 * @param {Array} CREATE_TABLE_CONFIG 表结构配置
 */
export class SqlLite<T> {
  CREATE_TABLE_CONFIG = null
  TABLE_NAME = null

  /**
   * 创建sqllite方法
   * - ** TS 泛型 必传
   * @param {string} TABLE_NAME 表名称
   * @param {Array} CREATE_TABLE_CONFIG 表结构配置
   */
  constructor(TABLE_NAME: string, CREATE_TABLE_CONFIG: SqlCreateItem[]) {
    this.CREATE_TABLE_CONFIG = CREATE_TABLE_CONFIG
    this.TABLE_NAME = TABLE_NAME
    this.startSql()
  }

  /** 打开表 */
  async startSql() {
    await openSqlite(this.TABLE_NAME)
    const isCreate = `SELECT count(*) as count FROM sqlite_master WHERE type='table' AND name='${this.TABLE_NAME}'`
    console.log('isCreate', isCreate)
    const count = await selectSql(this.TABLE_NAME, isCreate)
    const create = `CREATE TABLE IF NOT EXISTS ${this.TABLE_NAME} ${getCreateSql(this.CREATE_TABLE_CONFIG)}`
    console.log('create', create)
    console.log('count', count)
    if (count[0].count === 0) {
      await executeSql(this.TABLE_NAME, create)
    }
  }

  /**
   * 插入数据
   * @param {Array} arrs 数据 , 对象数组 - 只能传表结构内的字段
   */
  async insert(arrs: T[]) {
    const insetSql = `insert into ${this.TABLE_NAME} values ${getInsetSql<T>(this.CREATE_TABLE_CONFIG, arrs)}`
    return executeSql(this.TABLE_NAME, insetSql)
  }

  /**
   * 查询
   * @param {Object} query 查询条件 - 只能传表结构内的字段
   * @param {Object} pageconfig 分页条件
   */
  async search(query: Partial<T>, pageconfig?: QueryPage) {
    const searchSql = `select * from ${this.TABLE_NAME} ${getWhereSql<Partial<T>>(this.CREATE_TABLE_CONFIG, query)} ${getLimitSql(pageconfig)}`
    return selectSql(this.TABLE_NAME, searchSql)
  }

  /**
   * 修改
   * @param {Object} query 更新条件 - 只能传表结构内的字段
   * @param {Object} set 更新的数据对象 - 只能传表结构内的字段
   */
  async updata(query: Partial<T>, set: Partial<T>) {
    const updataSql = `update ${this.TABLE_NAME} ${getSetSql<Partial<T>>(this.CREATE_TABLE_CONFIG, set)} ${getWhereSql<Partial<T>>(this.CREATE_TABLE_CONFIG, query)}`
    return executeSql(this.TABLE_NAME, updataSql)
  }

  /**
   * 删除
   * @param {Array} arrs 数据 , 对象数组 - 只能传表结构内的字段
   */
  async delete(arrs: Partial<T>[]) {
    const deleteSql = `DELETE FROM ${this.TABLE_NAME} ${getDelsSql<Partial<T>>(this.CREATE_TABLE_CONFIG, arrs)}`
    return executeSql(this.TABLE_NAME, deleteSql)
  }

  /** 获取合计 */
  async countSql(query) {
    const countSql = `SELECT count(*) as count FROM ${this.TABLE_NAME} ${getWhereSql<Partial<T>>(this.CREATE_TABLE_CONFIG, query)}`
    const count = await selectSql(this.TABLE_NAME, countSql)
    console.log('count', count)
    return count[0].count
  }
}

// //新建表 account_tb
// create table if not exists account_tb ( 'id' integer primary key autoincrement,'name' varchar(255), 'gender' varchar(255), 'deptId' varchar(255))；
// //插入数据
// insert into account_tb values (null,'tyy','女', '2'),(null,'ty2','男', '22')；
// //修改数据
// update account_tb set name= '唐园园' where id=1;
// update account_tb2 set name= '唐园园', gender='543' where code='324' or code = '4324';
// update account_tb2 set name= '唐园园2', gender='543' where code='324' AND name = '唐园园';
// //删除数据
// delete from account_tb where id=1;
// //数据查询并分页(根据id 排序,搜索条件 gender)
// `select * from account_tb where gender='${gender}' order by 'id' asc limit ${pageSize*(pageNumber - 1)},${pageSize}`;
// //模糊查询like % %
// `select * from account_tb where name like ' %${gender}%' `;
// //连表查询(left/right/inner join  左/右/内 连接)
// `select * from account_tb inner join dept_tb as wd on account_tb.deptId = wd.id`;
// //获取总数并去重 （distinct 去重）
// select distinct count(*) as rowCount from account_tb；
// 批量删除
// DELETE from account_tb2 where code in ('324', '4324')

// 查询表是否存在
// SELECT count(*) as count FROM sqlite_master WHERE type='table' AND name=?
